package service

import (
	pb "bilinadmin/api/pb/server"
	"bilinadmin/internal/conf"
	"bilinadmin/internal/dao"
	"bilinadmin/pkg/lueerror"
	"bilinadmin/pkg/util"
	"context"
	"fmt"
	"strings"
)

type vendorSrv struct {
	*Service
	name string
	cfg  *conf.Config
}

const (
	APP_BILIN_WEB   = "bilin-web"
	APP_MALL_MOBILE = "mall-mobile"
)

var vSrv *vendorSrv

// InitVendorService 初始化第三方辑层
func InitVendorService(cfg *conf.Config) {
	vSrv = &vendorSrv{
		Service: service,
		name:    "brand_store_service",
		cfg:     cfg,
	}
}

// GetVendorService 获取品牌逻辑层
func GetVendorService() *vendorSrv {
	return vSrv
}

// GetJsApiParam 获取js api 参数
func (srv *vendorSrv) GetJsApiParam(ctx context.Context, uri string) (*pb.WechatMPJsParamsReply, lueerror.LueError) {
	res, err := dao.GetBilinVendorDao().GetWechatMPJsParams(ctx, uri)
	if err != nil {
		return nil, lueerror.OpenErr(err)
	}
	return &pb.WechatMPJsParamsReply{
		Noncestr:    res.Noncestr,
		JsapiTicket: res.JsapiTicket,
		Timestamp:   res.Timestamp,
		Url:         res.Url,
		Sign:        res.Sign,
		AppId:       res.AppId,
	}, nil
}

// OauthWechatMP 公众号授权
func (srv *vendorSrv) OauthWechatMP(ctx context.Context, code string) (*pb.OauthWechatMPReply, lueerror.LueError) {
	openId, err := dao.GetBilinVendorDao().OauthWechatMP(ctx, code)
	if err != nil {
		return nil, lueerror.OpenErr(err)
	}
	return &pb.OauthWechatMPReply{OpenId: openId}, nil
}

// AddressToLocation 地址坐标解析
func (srv *vendorSrv) AddressToLocation(ctx context.Context, address, region string) (*pb.AddressToLocationReply, lueerror.LueError) {
	if address == "" {
		return nil, nil
	}
	res, err := dao.GetBilinVendorDao().AddressToLocation(ctx, address, region)
	if err != nil {
		return nil, lueerror.LBSErr(err)
	}
	if res == nil {
		return &pb.AddressToLocationReply{}, nil
	}
	return &pb.AddressToLocationReply{
		Title:     res.Title,
		Latitude:  res.Latitude,
		Longitude: res.Longitude,
		CityCode:  res.CityCode,
		Province:  res.Province,
		City:      res.City,
		District:  res.District,
		Street:    res.Street,
		StreetNo:  res.StreetNo,
	}, nil
}

// LocationToAddress 坐标解析地址
func (srv *vendorSrv) LocationToAddress(ctx context.Context, lat, lng float64) (*pb.LocationToAddressReply, lueerror.LueError) {
	res, err := dao.GetBilinVendorDao().LocationToAddress(ctx, lat, lng)
	if err != nil {
		return nil, lueerror.LBSErr(err)
	}
	return &pb.LocationToAddressReply{
		CityCode: res.DistrictCode,
		Address:  res.Address,
		Nation:   res.Nation,
		Province: res.Province,
		City:     res.City,
		District: res.District,
		Street:   res.Street,
		StreetNo: res.StreetNo,
	}, nil
}

// AddressSearch 地址搜索
func (srv *vendorSrv) AddressSearch(ctx context.Context, keyword string, lat, lng float64) (*pb.AddressSearchReply, lueerror.LueError) {
	res, err := dao.GetBilinVendorDao().AddressSearch(ctx, keyword, lat, lng)
	if err != nil {
		return nil, lueerror.LBSErr(err)
	}
	rAdds := make([]*pb.AddressInfo, len(res))
	for idx, a := range res {
		rAdds[idx] = &pb.AddressInfo{
			Title:     a.Title,
			Address:   a.Address,
			Category:  a.Category,
			Latitude:  a.Latitude,
			Longitude: a.Longitude,
			Distance:  float32(a.Distance),
			CityCode:  a.CityCode,
		}
	}
	return &pb.AddressSearchReply{Addresses: rAdds}, nil
}

// GetQiniuUploadToken 获取七牛上传token
func (srv *vendorSrv) GetQiniuUploadToken(ctx context.Context, req *pb.GetQiniuUploadTokenReq) *pb.GetQiniuUploadTokenReply {
	if req == nil {
		return nil
	}
	token, expires := dao.GetBilinVendorDao().GetQiqiuUploadToken(ctx, req.Bucket, req.OverwriteKey, 0)
	return &pb.GetQiniuUploadTokenReply{
		Token:   token,
		Expires: expires,
	}
}

func CosAllowApp(app string, allowdApps string) bool {
	return util.Contains(allowdApps, app)
}

// ListCosBucketSets 获取app对应的cos bucket set
func (srv *vendorSrv) ListCosBucketSets(ctx context.Context, app string) (*pb.ListCosBucketSetsReply, lueerror.LueError) {

	bucketSets := []*pb.CosBucketSet{}
	for idx, bucket := range srv.cfg.Cos.Buckets {
		if CosAllowApp(app, srv.cfg.Cos.AllowApps[idx]) {
			bucketParts := util.SplitString(bucket, "-")
			bucketParts = bucketParts[:len(bucketParts)-1]
			prefix := strings.Join(bucketParts, "-")
			bucketSets = append(bucketSets, &pb.CosBucketSet{
				Prefix:       prefix,
				Bucket:       bucket,
				Region:       srv.cfg.Cos.Regions[idx],
				CustomDomain: srv.cfg.Cos.CustomDomains[idx],
			})
		}
	}
	return &pb.ListCosBucketSetsReply{
		BucketSets: bucketSets,
	}, nil
}

// GetCosAuthorization 获取cos上传 authorization
func (srv *vendorSrv) GetCosAuthorization(ctx context.Context, req *pb.GetCosAuthorizationReq) (*pb.GetCosAuthorizationReply, lueerror.LueError) {
	if req == nil {
		return nil, lueerror.InvalidRequest(fmt.Errorf("parse request err"))
	}
	bucket := fmt.Sprintf("%s-%s", req.BucketPrefix, srv.cfg.Cos.AppID)
	idx := util.IndexOfStr(srv.cfg.Cos.Buckets, bucket)
	if -1 == idx {
		return nil, lueerror.CosErr(fmt.Errorf("no permission for %s", req.BucketPrefix))
	}
	region := srv.cfg.Cos.Regions[idx]

	credentials, err := dao.GetBilinVendorDao().GetCosAuthorization(ctx, bucket, region)
	if err != nil {
		return nil, lueerror.CosErr(err)
	}
	return &pb.GetCosAuthorizationReply{
		Credentials: credentials,
		Bucket:      bucket,
		Region:      region,
	}, nil
}
